#include "MultiSnake.h"
#include "../Snake/Snake.h"
#include "qtimer.h"
#include "qlist.h"

MultiSnake::MultiSnake(QWidget* parent, int cellNum, int cellLen) : Snake(parent, cellNum, cellLen)
{
}

MultiSnake::~MultiSnake() {
};

void MultiSnake::doGameLogic() {
	updateCurrentPlayer();
	updateOtherPlayers();

}
void MultiSnake::updateOtherPlayers() {
	QSet<Player*>::const_iterator i;
	Player* other;
	for (i = this->otherSnakes->constBegin(); i != this->otherSnakes->constEnd(); ++i) {
		other = (*i);
		QQueue<QPoint>* currentSnake = other->player;
		QPoint delPoint;
		QPoint snakeHead = currentSnake->last();
		int newCellX = snakeHead.x();
		int newCellY = snakeHead.y();
		if (other->die) {
			continue;
		}
		switch (other->direct) {
		case UP:
			newCellY -= 1;
			break;
		case DOWN:
			newCellY += 1;
			break;
		case LEFT:
			newCellX -= 1;
			break;
		case RIGHT:
			newCellX += 1;
			break;
		}
		QList<QPoint>::const_iterator point;

		switch (board[newCellX][newCellY]) {
		case SNAKEBODY:
			other->die = true;
			for (point = currentSnake->begin(); point != currentSnake->end();++point) {
				board[(*point).x()][(*point).y()] = FOOD;
			}
			break;
		case NOTHING:
			currentSnake->enqueue(QPoint(newCellX, newCellY));
			delPoint = currentSnake->dequeue();
			board[snakeHead.x()][snakeHead.y()] = SNAKEBODY;
			board[newCellX][newCellY] = SNAKEHEAD;
			board[delPoint.x()][delPoint.y()] = NOTHING;
			break;
		case FOOD:
			currentSnake->enqueue(QPoint(newCellX, newCellY));
			board[snakeHead.x()][snakeHead.y()] = SNAKEBODY;
			board[newCellX][newCellY] = SNAKEHEAD;
			generateFood();
			break;
		case WALL:
			other->die = true;
			for (point = currentSnake->begin(); point != currentSnake->end();++point) {
				board[(*point).x()][(*point).y()] = FOOD;
			}
			break;

		}
	}

}

void MultiSnake::keyEvent(QKeyEvent* event) {
	Player* other = *(this->otherSnakes->constBegin());
	switch (event->key()) {
	case Qt::Key_Up:
		newDirect = UP;
		break;
	case Qt::Key_Down:
		newDirect = DOWN;
		break;
	case Qt::Key_Left:
		newDirect = LEFT;
		break;
	case Qt::Key_Right:
		newDirect = RIGHT;
		break;
	case Qt::Key_W:
		other->newDirect = UP;
		break;
	case Qt::Key_S:
		other->newDirect = DOWN;
		break;
	case Qt::Key_A:
		other->newDirect = LEFT;
		break;
	case Qt::Key_D:
		other->newDirect = RIGHT;
		break;
	}
}


void MultiSnake::init() {
	initGame();
	initCurrentPlayer();
	initOtherPlayers();
	generateFood();
	startGameLoop();
}

void MultiSnake::doKeyEvent() {
	__super::doKeyEvent();
	Player* other = *(this->otherSnakes->constBegin());

	switch (other->newDirect) {
	case UP:
		if (other->direct != DOWN) {
			other->direct = UP;
		}
		break;
	case DOWN:
		if (other->direct != UP) {
			other->direct = DOWN;
		}
		break;
	case LEFT:
		if (other->direct != RIGHT) {
			other->direct = LEFT;
		}
		break;
	case RIGHT:
		if (other->direct != LEFT) {
			other->direct = RIGHT;
		}
		break;
	}
}


void MultiSnake::initOtherPlayers() {
	Player* player = new Player();
	player->direct = LEFT;
	player->newDirect = LEFT;
	player->player->clear();
	player->player->enqueue(QPoint(cellNumX - 1 - 1, cellNumY / 2));
	player->player->enqueue(QPoint(cellNumX - 2 - 1, cellNumY / 2));
	player->player->enqueue(QPoint(cellNumX - 3 - 1, cellNumY / 2));
	board[cellNumX - 1 - 1][cellNumY / 2] = SNAKEBODY;
	board[cellNumX - 2 - 1][cellNumY / 2] = SNAKEBODY;
	board[cellNumX - 3 - 1][cellNumY / 2] = SNAKEHEAD;
	this->otherSnakes->insert(player);
}

bool operator==(const Player& left, const Player& right) {
	bool result = left.player->size() == right.player->size();
	if (result) {
		return result;
	}
	if (left.player != right.player) {
		return false;
	}
	return true;
}

uint qHash(const Player& player) {
	return qHash(player.player);
}



